<!--
 * @Description: 床位管理页面（左右分栏：左-事项提醒，右-床位管理）
 * @Author: 系统
 * @Date: 2025-11-12 14:15:00
 * @LastEditors: 梁青春
 -->
<template>
  <navbar>
    <template #left-pick>
      <div class="dropdown">
        <el-dropdown>
          <span class="el-dropdown-link">
            {{ selectedWard?.wardName }}
            <el-icon class="el-icon--right">
              <arrow-down />
            </el-icon>
          </span>
          <template #dropdown>
            <el-dropdown-menu>
              <el-dropdown-item v-for="ward in leftWardList" :key="ward.id" @click="selectWard(ward)">
                {{ ward.wardName }}
              </el-dropdown-item>
            </el-dropdown-menu>
          </template>
        </el-dropdown>
      </div>
    </template>
  </navbar>
  <!-- 使用全局 Container 组件，保持与既有功能一致的风格 -->
  <Container :showLeft="true" :showRight="false" leftWidth="320px">
    <template #left>
      <div class="reminder" v-loading="leftLoading">
        <div class="reminder__header left-heard">提醒事项</div>

        <section class="reminder__group">
          <h4 class="reminder__group-title">患者待办</h4>
          <div class="reminder__grid">
            <el-popover placement="bottom" trigger="click" width="420px" popper-class="assign-popover">
              <template #reference>
                <div class="reminder__card" @click="leftOnOpenAssign">
                  <div class="reminder__count">{{ leftStats.pendingAssign || pendingAssign.length }}</div>
                  <div class="reminder__label">待分配床位</div>
                </div>
              </template>
              <template #default>
                <div class="assign-list" v-loading="leftAssignLoading">
                  <div class="assign-item" v-for="p in pendingAssign" :key="p.id" @click="leftOnAssignClick(p)">
                    <span class="assign-name">{{ p.name }}</span>
                    <span class="assign-sex iconfont" :class="p.sex === 2 ? 'icon-woman' : 'icon-man'"></span>
                    <span class="assign-time">{{ p.admissionTime }}</span>
                    <span class="assign-dept">{{ p.dept }}</span>
                  </div>
                </div>
                <div class="add-admission">
                  <el-button type="primary" :icon="Plus" @click="leftOnOpenRegister">新增入院患者</el-button>
                </div>
              </template>
            </el-popover>

            <div class="reminder__card">
              <div class="reminder__count">{{ leftStats.arrears }}</div>
              <div class="reminder__label">已欠费</div>
            </div>

            <div class="reminder__card">
              <div class="reminder__count">{{ leftStats.dischargeTransfer }}</div>
              <div class="reminder__label">出院/转科</div>
            </div>
          </div>
        </section>

        <section class="reminder__group">
          <h4 class="reminder__group-title">医嘱待办</h4>
          <div class="reminder__grid">
            <div class="reminder__card">
              <div class="reminder__count">{{ leftStats.orderVerify }}</div>
              <div class="reminder__label">待核对</div>
            </div>
            <div class="reminder__card">
              <div class="reminder__count">{{ leftStats.orderExecute }}</div>
              <div class="reminder__label">待执行</div>
            </div>
            <div class="reminder__card">
              <div class="reminder__count">{{ leftStats.orderStopRevoke }}</div>
              <div class="reminder__label">停止/撤销</div>
            </div>
          </div>
        </section>
      </div>
    </template>
    <RegisterAdmissionDialog v-model="leftRegisterVisible" @submitted="leftOnRegistered" />

    <div class="bed-main container-body" v-loading="rightLoading">
      <div class="query-bar main-herard">
        <el-radio-group v-model="rightStatus" @change="rightOnStatusChange">
          <el-radio-button label="">全部</el-radio-button>
          <el-radio-button label="1">在院</el-radio-button>
          <el-radio-button label="2">待出院</el-radio-button>
          <el-radio-button label="3">新入</el-radio-button>
          <el-radio-button label="4">病危</el-radio-button>
          <el-radio-button label="5">欠费</el-radio-button>
          <el-radio-button label="6">空床</el-radio-button>
        </el-radio-group>
        <div class="picker">
          <el-popover placement="bottom" trigger="click" width="360px" popper-class="filter-box">
            <template #reference>
              <el-button text :icon="Filter" @click="rightOnOpenFilter">筛选</el-button>
            </template>
            <template #default>
              <div class="filter-content">
                <div class="filter-item">
                  <el-input v-model="rightFilters.keyword" placeholder="患者姓名" clearable />
                </div>
                <div class="filter-item">
                  <el-select v-model="rightFilters.doctors" multiple placeholder="主管医生">
                    <el-option
                      v-for="doctor in rightDoctorOptions"
                      :key="doctor.userId"
                      :label="doctor.nickName"
                      :value="doctor.userId"
                    />
                  </el-select>
                </div>
              </div>
              <div class="filter-btns">
                <el-button @click="rightOnResetFilters">取消</el-button>
                <el-button type="primary" @click="rightOnApplyFilters">应用</el-button>
              </div>
            </template>
          </el-popover>
        </div>
      </div>

      <div class="card-grid">
        <BedCard
          v-for="item in bedCards"
          :key="item.id"
          :item="item"
          @assign="rightHandleAssign"
          @detail="rightHandleDetail"
          @changeBed="rightHandleChangeBed"
          @discharged="rightHandleDischarged"
        />
      </div>
    </div>
    <AssignDialog
      v-model="assignVisible"
      :ward="selectedWard"
      :deptName="currentDeptName"
      :defaultPatientId="defaultPatientId"
      :patientOptions="patientOptions"
      :bedOptions="bedOptions"
      :defaultBedId="defaultBedId"
      @submitted="handleAssigned"
    />
    <PatientDetailDialog v-model="rightDetailVisible" :patient="rightDetailPatient" :admission="rightDetailAdmission" />
    <ChangeBedDialog
      v-model="changeBedVisible"
      :patient="changeBedPatient"
      :currentBedNo="changeBedCurrentNo"
      :beds="changeBedOptions"
      @confirm="handleChangeBedConfirm"
    />
  </Container>
</template>

<script setup name="Beds">
import { ref, reactive, computed, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { debounce } from '@/utils/index'
import mockBedApi from '@/mock/bed'
import { getTodoStats, getWardList, getBedsList, getAdmissionDetail, getPatientList } from '@/api/nurseWork/beds.js'
import { listUserByPostCode } from '@/api/system/user'

import { Plus, Filter } from '@element-plus/icons-vue'
import BedCard from './components/BedCard.vue'
import AssignDialog from './components/AssignDialog.vue'
import RegisterAdmissionDialog from '@/views/chargingWork/admissionRegistration/components/RegisterAdmissionDialog.vue'
import PatientDetailDialog from './components/PatientDetailDialog.vue'
import ChangeBedDialog from './components/ChangeBedDialog.vue'

// 常量
const ASSIGN_DEBOUNCE_MS = 300
const STATUS_DEBOUNCE_MS = 200
const FILTER_DEBOUNCE_MS = 200

// 数据 - 左侧区域
const leftLoading = ref(false)
const leftAssignLoading = ref(false)
const leftStats = ref({
  pendingAssign: 0,
  arrears: 0,
  dischargeTransfer: 0,
  orderVerify: 0,
  orderExecute: 0,
  orderStopRevoke: 0
})
const pendingAssign = ref([])
const assignVisible = ref(false)
const defaultPatientId = ref('')
const patientOptions = ref([])
const bedOptions = ref([])
const currentDeptName = ref('')
const leftRegisterVisible = ref(false)
const leftWardList = ref([])
const selectedWard = ref({})
const defaultBedId = ref('')

// 数据 - 右侧区域
const rightLoading = ref(false)
const bedCards = ref([])
const rightStatus = ref('')
const rightDoctorOptions = ref([])
const rightFilters = ref({ keyword: null, doctors: null })

const rightDetailVisible = ref(false)
const rightDetailPatient = ref({})
const rightDetailAdmission = ref({})
const changeBedVisible = ref(false)
const changeBedPatient = ref({})
const changeBedCurrentNo = ref('')
const changeBedOptions = ref([])

// 计算属性（占位，便于后续扩展）
const leftPendingCount = computed(() => leftStats.value.pendingAssign)

// 方法 - 左侧：统计与分配
const loadTodoStats = async () => {
  try {
    leftLoading.value = true
    const res = await getTodoStats()
    if (res.code === 200) {
      leftStats.value = res.data ?? {
        pendingAssign: 0,
        arrears: 0,
        dischargeTransfer: 0,
        orderVerify: 0,
        orderExecute: 0,
        orderStopRevoke: 0
      }
    } else {
      ElMessage.error('获取事项提醒失败')
    }
  } catch (e) {
    ElMessage.error('网络异常，稍后重试')
  } finally {
    leftLoading.value = false
  }
}
const openAssignList = debounce(
  async () => {
    try {
      leftAssignLoading.value = true
      const res = await getPatientList({ wardId: selectedWard.value.wardId })
      if (res.code === 200) {
        pendingAssign.value = res.data
        patientOptions.value = [...res.data]
      } else {
        ElMessage.error('获取待分配列表失败')
      }
    } catch (e) {
      ElMessage.error('网络异常，稍后重试')
    } finally {
      leftAssignLoading.value = false
    }
  },
  ASSIGN_DEBOUNCE_MS,
  false
)
const openAssignDialog = debounce(
  async patient => {
    defaultPatientId.value = patient?.id || ''
    assignVisible.value = true
  },
  ASSIGN_DEBOUNCE_MS,
  true
)
const openRegisterDialog = () => {
  leftRegisterVisible.value = true
}

// 左侧：新增患者
const handleRegistered = () => {
  loadTodoStats()
}
// 左侧：病区列表
const loadWardList = async () => {
  try {
    const res = await getWardList()
    if (res.code === 200) {
      leftWardList.value = res.data
      if (res.data.length > 0) {
        selectedWard.value = leftWardList.value[0]
        loadBedCards()
        openAssignList()
      }
    } else {
      console.error('获取病区列表失败')
    }
  } catch (e) {
    console.error('网络异常，稍后重试')
  }
}
// 右侧：病区选择
const selectWard = ward => {
  selectedWard.value = ward
  loadBedCards()
  openAssignList()
}

// 方法 - 右侧：床卡列表与筛选
const initRightPanel = async () => {
  try {
    rightLoading.value = true
    const [dRes] = await Promise.all([listUserByPostCode('doctor')])
    if (dRes.code === 200) rightDoctorOptions.value = dRes.rows
  } catch (e) {
    console.error('初始化失败，请稍后重试', e)
  } finally {
    rightLoading.value = false
  }
}
const loadBedCards = async () => {
  try {
    rightLoading.value = true
    const res = await getBedsList({
      wardId: selectedWard.value.wardId,
      status: rightStatus.value,
      searchKey: rightFilters.value.keyword,
      residentDoctor: rightFilters.value.doctors
    })
    if (res.code === 200) {
      bedCards.value = res.data
      bedOptions.value = [...res.data]
    } else {
      console.error('获取床位数据失败', res)
    }
  } catch (e) {
    console.error('网络异常，稍后重试', e)
  } finally {
    rightLoading.value = false
  }
}
const changeStatus = debounce(() => loadBedCards(), STATUS_DEBOUNCE_MS, false)
const openFilter = debounce(() => {}, FILTER_DEBOUNCE_MS, false)
const applyFilters = debounce(() => loadBedCards(), FILTER_DEBOUNCE_MS, true)
const resetFilters = debounce(
  () => {
    rightFilters.value = { keyword: null, doctors: null }
    loadBedCards()
  },
  FILTER_DEBOUNCE_MS,
  true
)

// 方法 - 右侧：详情与分配
const openDetail = async item => {
  try {
    const res = await getAdmissionDetail({ hospitalizationNumber: item.hospitalizationNumber })
    if (res.code === 200) {
      const d = res.data || {}
      rightDetailPatient.value = d.patientInfo || d.patient || {}
      rightDetailAdmission.value = d.admissionInfo || d.admission || {}
      rightDetailVisible.value = true
    } else {
      console.error('获取患者详情失败', res)
    }
  } catch (e) {
    console.error('网络异常，稍后重试', e)
  }
}
const changeBed = item => {
  changeBedPatient.value = item || {}
  changeBedCurrentNo.value = String(item.bedNo || '')
    .replace(/床$/, '')
    .padStart(2, '0')
  changeBedOptions.value = [...bedOptions.value, { bedId: '99999', bedNo: '拟' }]
  changeBedVisible.value = true
}
// 右侧：分配确认
const handleAssigned = payload => {
  loadBedCards()
}
// 右侧：出院确认
const handleDischarged = item => {
  loadBedCards()
}

// 右侧：换床
const openAssign = async item => {
  try {
    rightLoading.value = true
    defaultBedId.value = item.bedId
    assignVisible.value = true
  } catch (e) {
    console.error('打开分配弹窗失败')
  } finally {
    rightLoading.value = false
  }
}
// 右侧：换床确认
const handleChangeBedConfirm = target => {
  loadBedCards()
}

// 生命周期
onMounted(() => {
  loadTodoStats()
  loadWardList()
  initRightPanel()
})

// 事件暴露给模板（命名规范：动词+名词）
const leftOnOpenAssign = openAssignList
const leftOnAssignClick = openAssignDialog
const leftOnOpenRegister = openRegisterDialog
const leftOnRegistered = handleRegistered

const rightOnStatusChange = changeStatus
const rightOnOpenFilter = openFilter
const rightOnApplyFilters = applyFilters
const rightOnResetFilters = resetFilters
const rightHandleDetail = openDetail
const rightHandleChangeBed = changeBed
const rightHandleDischarged = handleDischarged
const rightHandleAssign = openAssign
</script>

<style lang="scss" scoped>
@use '@/assets/styles/variables.module.scss' as *;
.dropdown {
  height: 100%;
  display: flex;
  align-items: center;
  cursor: pointer;
}
.reminder {
  height: 100%;
  background: #fff;
  display: flex;
  flex-direction: column;
  border-right: 1px solid $border-color;
}
.reminder__header {
  display: flex;
  align-items: center;
  font-size: $font-size;
}
.reminder__group {
  padding: $padding-md;
}
.reminder__group-title {
  font-size: $font-size-sm;
  color: #606266;
  margin-bottom: $margin-sm;
  font-weight: 600;
}
.reminder__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: $margin-md;
}
.reminder__card {
  border: 1px solid $border-color;
  border-radius: $border-radius;
  padding: $padding-md;
  background: #fff;
  box-shadow: 0 2px 12px 0 $box-shadow-color;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: all 0.2s ease-in-out;
  &:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 16px 0 $box-shadow-color;
    background-color: $light-bg;
  }
  &:active {
    transform: translateY(0);
    box-shadow: 0 2px 12px 0 $box-shadow-color;
  }
}
.reminder__count {
  font-size: $font-size-xl;
  font-weight: 700;
  line-height: 1.2;
}
.reminder__label {
  margin-top: 6px;
  font-size: $font-size-sm;
  color: #606266;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
@media (max-width: 1024px) {
  .reminder__grid {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (max-width: 640px) {
  .reminder__grid {
    grid-template-columns: 1fr;
  }
}
.assign-list {
  max-height: 280px;
  overflow-y: auto;
}
.assign-item {
  display: grid;
  grid-template-columns: 56px 24px 128px 1fr;
  align-items: center;
  padding: 6px 8px;
  border-radius: $border-radius;
  transition: background-color 0.2s ease-in-out;
  &:hover {
    background: #f5f7fa;
  }
}
.assign-name {
  color: $blue;
  font-weight: bold;
  cursor: pointer;
}
.assign-sex {
  color: $icon-color;
}
.assign-time {
  color: #909399;
  font-size: $font-size-sm;
}
.assign-dept {
  color: #606266;
  font-size: $font-size-sm;
}
.add-admission {
  width: 100%;
  margin-top: $margin-sm;
  padding-top: $padding-sm;
  border-top: 1px solid $border-color;
  display: flex;
  align-items: center;
  justify-content: center;
}
.bed-main {
  display: flex;
  flex-direction: column;
}
.query-bar {
  display: flex;
  align-items: center;
}
.card-grid {
  padding: $padding-md;
  display: flex;
  flex-wrap: wrap;
  gap: $margin-md;
  max-height: 100%;
  overflow-y: auto;
}
</style>
<style lang="scss">
@use '@/assets/styles/variables.module.scss' as *;
.filter-box {
  width: 100%;
  display: flex;
  flex-direction: column;
  --el-popover-padding: 0;
  .filter-content {
    width: 100%;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    padding: $padding-sm;
    gap: $margin-sm;
    .filter-item {
      width: 48%;
      display: flex;
    }
  }
  .filter-btns {
    padding: $padding-sm;
    width: 100%;
    display: flex;
    margin-top: $margin-sm;
    border-top: 1px solid $border-color;
    justify-content: flex-end;
    align-items: center;
  }
}
</style>
